<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * call apply bind 为什么要使用这些?
    * 1.改变this指向 2.传参方式
    *
    * */
    var a = {
        user:"remi",
        fn:function (a,b){
            console.log(this.user+a+b)
        }
    }
    a.fn() //remi 谁调用指向谁
    var b = a.fn //b是一个全局变量 window下面没有user属性 访问对象不存在的属性 就是undefined
    b() //undefined
    b.call(a) //第一个参数 就是this指向需要指向的对象
    b.apply(a) //
    b.bind(a)() //bind不是立马执行，而是返回一个新的函数，所以需要加（）来执行调用

    //call 和 apply 是立马执行函数 bind是返回一个新的函数，需要再加一个括号去执行
    //call传参：b.call(a,1,2) 第一个参数 就是this指向需要指向的对象,后面都是传入的参数，以逗号分隔
    //apply传参：b.apply(a,[1,2]) 第一个参数 就是this指向需要指向的对象,第二个参数是数组，
    //注意:arguments也是一个数组，如果 第二个参数 要传arguments，用apply，注意是第二个参数是数组
    //Array.prototype.join.call(arguments,",")这里第二个参数是一个字符串逗号，所以可以用call
    //bind传参很灵活，可以一次性传完，也可以分批次传参


    function join(arr){
        arr.join(",") //这是表示数组按照什么方式合并为字符串
        //原本this指向传进来的数组arr
        //当我们写了第一行代码，this指向还可以指向传进来的arg
        Array.prototype.join.call(arguments,",") //第一行代码
        join.call(arguments) //arguments使用数组的方法join，按照","的方式转换成字符串
    }

    //下面的代码接28行以上的代码
    var b = a.fn
    var c = b.bind(a,1,2) //一次性传完1 2，但没有执行
    c() //这里才执行

    var d = b.bind(a,1) //第一次传一个参数1
    d(2) //执行的时候又再传一个参数2

    var e = b.bind(a) //只传this指向的参数对象
    e(1,2) //执行时候传完参数


</script>
</body>
</html>